package com.bizmda.bizsip.app.checkrule;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author shizhengye
 */
@Slf4j
public class FieldCheckRuleFunction {

    private static final String MONEY_PATTERN = "^([1-9]\\d*(\\.\\d{1,2})?|([0](\\.([0][1-9]|[1-9]\\d{0,1}))))$";
    private static final String NUMBER_PATTERN = "[0-9]*";

    private FieldCheckRuleFunction() {

    }

    /**
     * 验证是否为身份证号码（支持18位、15位和港澳台的10位）
     */
    public static boolean isCitizenId(Object value, List<Object> args) {
        log.trace("isCitizenId({},{})", value, args);
        return Validator.isCitizenId((String) value);
    }

    public static boolean isEmail(Object value, List<Object> args) {
        log.trace("isEmail({},{})", value, args);
        return Validator.isEmail((String) value);
    }

    /**
     * 邮箱格式且可为空
     */
    public static boolean isEmailCanNull(Object value, List<Object> args) {
        if(StrUtil.isBlankIfStr(value)){
            return true;
        }
        log.trace("isEmailCanNull({},{})", value, args);
        return Validator.isEmail((String) value);
    }
    /**
     * 通过正则表达式验证，可为空
     */
    public static boolean isMatchRegexCanNull(Object value, List<Object> args) {
        if(StrUtil.isBlankIfStr(value)){
            return true;
        }
        log.trace("isMatchRegex({},{})", value, args);
        return Validator.isMatchRegex((String) args.get(0), (String) value);
    }

    public static boolean notEmpty(Object value, List<Object> args) {
        log.trace("notEmpty({},{})", value, args);
        return !Validator.isEmpty(value);
    }

    /**
     * 通过正则表达式验证
     */
    public static boolean isMatchRegex(Object value, List<Object> args) {
        log.trace("isMatchRegex({},{})", value, args);
        return Validator.isMatchRegex((String) args.get(0), (String) value);
    }

    /**
     * 验证是否为金额，单位元2位小数
     */
    public static boolean isMoney(Object value, List<Object> args) {
        log.trace("isMoney({},{})", value, args);
        return Validator.isMatchRegex("([1-9]\\d*|0)(\\.\\d{1,2})?", (String) value);
    }

    /**
     * 验证是否为金额，单位分支持
     */
    public static boolean isCent(Object value, List<Object> args) {
        log.trace("isCent({},{})", value, args);
        return Validator.isMatchRegex("[1-9]\\d*", (String) value);
    }


    /**
     * 验证是否为URL
     */
    public static boolean isUrl(Object value, List<Object> args) {
        log.trace("isUrl({},{})", value, args);
        return Validator.isUrl((String) value);
    }

    /**
     * 验证该字符串是否是数字
     */
    public static boolean isNumber(Object value, List<Object> args) {
        log.trace("isNumber({},{})", value, args);
        return Validator.isNumber((String) value);
    }

    /**
     * 验证是否为手机号码（中国）
     */
    public static boolean isMobile(Object value, List<Object> args) {
        log.trace("isMobile({},{})", value, args);
        return Validator.isMobile((String) value);
    }

    /**
     * 验证给定的数字是否在指定范围内
     */
    public static boolean isBetween(Object value, List<Object> args) {
        log.trace("isBetween({},{})", value, args);
        return Validator.isBetween(Double.valueOf(value.toString()), Integer.valueOf(args.get(0).toString()), Integer.valueOf(args.get(1).toString()));
    }

    /**
     * 验证时间格式
     */
    public static boolean checkTimeFormatter(Object value, List<Object> args) {
        log.trace("checkTimeFormatter({},{})", value, args);
        try {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern((String) args.get(0));
            // 格式验证
            LocalDateTime.parse((String) value, formatter);
        } catch (DateTimeParseException | NullPointerException e) {
            return false;
        }
        return true;
    }

    /**
     * 验证给定的字符传长度是否在指定范围内
     */
    public static boolean isLengthBetween(Object value, List<Object> args) {
        log.trace("isLengthBetween({},{})", value, args);
        int length = value.toString().length();
        return length >= Integer.parseInt((String) args.get(0))
                && length <= Integer.parseInt((String) args.get(1));
    }



    public static boolean isEmailAndM(Object value,List<Object> args) {
        log.debug("isEmailAndM({},{})",value,args);
        if(ObjectUtil.length(value) > (int) args.get(0)){
            return false;
        }
        return Validator.isEmail((String)value);
    }


    /**
     * 字符串是否为空判断 包含null和空格
     * @param value 数值
     * @param args 参数
     * @return 返回是否为空 false:空 true:不为空
     */
    public static boolean notBlank(Object value, List<Object> args) {
        log.debug("notBlank({}{})", value, args);
        return !StrUtil.isBlankIfStr(value);
    }

    /**
     * 判断是否超过最大值
     * @param value 数值
     * @param args 参数
     * @return 返回是否大于最大值
     */
    public static boolean isGtMaxLength(Object value, List<Object> args) {
        log.debug("isGtMaxLength({}{})", value, args);
        return ObjectUtil.length(value) <= (Integer) args.get(0);
    }

    /**
     * 是否为整数
     * @param value 数值
     * @param args 参数
     * @return 返回
     */
    public static boolean notInteger(Object value, List<Object> args) {
        log.debug("notInteger({}{})", value, args);
        return NumberUtil.isInteger((String) value);
    }

    /**
     * 是否正整数
     * @param value 数值
     * @param args 参数
     * @return 返回
     */
    public static boolean isPositiveInterger(Object value, List<Object> args) {
        log.debug("isPositiveInterger({}{})", value, args);
        if (!NumberUtil.isInteger((String) value)) {
            return false;
        }
        return Integer.parseInt(String.valueOf(value)) > 0;
    }

    /**
     * 判断是否日期格式
     * @param value 数据值
     * @param args 参数
     * @return 返回
     */
    public static boolean isDatePattern(Object value, List<Object> args) {
        log.debug("isDatePattern({}{})", value, args);
        try {
            String v = (String) value;
            String arg = (String) args.get(0);
            if (arg.length() != v.length()) {
                return false;
            }
            SimpleDateFormat format = new SimpleDateFormat(arg);
            //设置lenient为false. 否则SimpleDateFormat会比较宽松地验证日期，比如2007/02/29会被接受，并转换成2007/03/01
            format.setLenient(false);
            Date date = format.parse(v);
            return v.equals(format.format(date));
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 判断是固定长度
     * @param value 数值
     * @param args 参数
     * @return 返回是否大于最大值
     */
    public static boolean isEqualsLength(Object value, List<Object> args) {
        log.debug("isEqualsLength({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return true;
        }
        return ObjectUtil.length(value) == (int) args.get(0);
    }

    /**
     * 判断是否在长度区间内
     * @param value 数值
     * @param args 参数
     * @return 返回是否大于最大值
     */
    public static boolean isInSectionLength(Object value, List<Object> args) {
        log.debug("isInSectionLength({}{})", value, args);
        try {
            if(ObjectUtil.length(value) < (int) args.get(0)){
                return false;
            }
            return ObjectUtil.length(value) <= (int) args.get(1);
        }catch (Exception e){
            log.error("校验参数异常isInSectionLength:",e);
            return false;
        }

    }

    /**
     * 判断是否超过最大值且非空
     * @param value 数值
     * @param args 参数
     * @return 返回是否大于最大值
     */
    public static boolean isGtMaxLengthAndM(Object value, List<Object> args) {
        log.debug("isGtMaxLengthAndM({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return false;
        }
        return ObjectUtil.length(value) <= (Integer) args.get(0);
    }

    /**
     * 是否为整数且非空
     * @param value 数值
     * @param args 参数
     * @return 返回
     */
    public static boolean notIntegerAndM(Object value, List<Object> args) {
        log.debug("notIntegerAndM({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return false;
        }
        return NumberUtil.isInteger((String) value);
    }

    /**
     * 是否正整数且非空
     * @param value 数值
     * @param args 参数
     * @return 返回
     */
    public static boolean isPositiveIntergerAndM(Object value, List<Object> args) {
        log.debug("isPositiveIntergerAndM({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return false;
        }
        if (!NumberUtil.isInteger((String) value)) {
            return false;
        }
        return Integer.parseInt(String.valueOf(value)) > 0;
    }

    /**
     * 判断是否日期格式且非空
     * @param value 数据值
     * @param args 参数
     * @return 返回
     */
    public static boolean isDatePatternAndM(Object value, List<Object> args) {
        log.debug("isDatePattern({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return false;
        }
        return isDatePattern(value, args);
    }

    /**
     * 判断是否金额格式，小数点后两位且非空
     * @param value 数据值
     * @param args 参数
     * @return 返回
     */
    public static boolean isMoneyAndM(Object value, List<Object> args){
        log.debug("isMoneyAndM({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return false;
        }
        String regMoney = MONEY_PATTERN;// 金额正则,可以没有小数，小数最多不超过两位
        Pattern pattern = Pattern.compile(regMoney);
        Matcher matcher = pattern.matcher((String)value);
        return matcher.matches();
    }

    /**
     * 判断是否金额格式，小数点后两位且非空,且校验最大长度,大于0
     * @param value 数据值
     * @param args 参数
     * @return 返回
     */
    public static boolean isMoneyWithMaxLen(Object value, List<Object> args){
        log.debug("isMoneyWithMaxLen({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return true;
        }
        if(ObjectUtil.length(value) > (int) args.get(0)){
            return false;
        }
        String regMoney = MONEY_PATTERN;// 金额正则,可以没有小数，小数最多不超过两位
        Pattern pattern = Pattern.compile(regMoney);
        Matcher matcher = pattern.matcher((String)value);
        return matcher.matches();
    }

    /**
     * 判断是否金额格式，小数点后两位且非空,且校验最大长度
     * @param value 数据值
     * @param args 参数
     * @return 返回
     */
    public static boolean isMoneyWithMaxLenAndM(Object value, List<Object> args){
        log.debug("isMoneyWithMaxLenAndM({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return false;
        }
        if(ObjectUtil.length(value) > (int) args.get(0)){
            return false;
        }
        String regMoney = MONEY_PATTERN;// 金额正则,可以没有小数，小数最多不超过两位
        Pattern pattern = Pattern.compile(regMoney);
        Matcher matcher = pattern.matcher((String)value);
        return matcher.matches();
    }

    /**
     * 判断是固定长度且非空
     * @param value 数值
     * @param args 参数
     * @return 返回是否大于最大值
     */
    public static boolean isEqualsLengthAndM(Object value, List<Object> args) {
        log.debug("isEqualsLengthAndM({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return false;
        }
        return ObjectUtil.length(value) == (int) args.get(0);
    }

    /**
     * 判断是否在长度区间内且非空
     * @param value 数值
     * @param args 参数
     * @return 返回是否大于最大值
     */
    public static boolean isInSectionLengthAndM(Object value, List<Object> args) {
        log.debug("isInSectionLengthAndM({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return false;
        }
        try {
            if(ObjectUtil.length(value) < (int) args.get(0)){
                return false;
            }
            return ObjectUtil.length(value) <= (int) args.get(1);
        }catch (Exception e){
            log.error("校验参数异常isInSectionLengthAndM:",e);
            return false;
        }
    }

    /**
     * 判断是否在为数字字符串，手机号和卡号校验
     * @param value 数值
     * @param args 参数
     * @return 返回是否大于最大值
     */
    public static boolean isNumeric(Object value, List<Object> args){
        log.debug("isNumeric({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return true;
        }
        return Pattern.matches(NUMBER_PATTERN,(String)value);
    }
    /**
     * 判断是否在为数字字符串，手机号和卡号校验,且非空
     * @param value 数值
     * @param args 参数
     * @return 返回是否大于最大值
     */
    public static boolean isNumericAndM(Object value, List<Object> args){
        log.debug("isNumeric({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return false;
        }
        return Pattern.matches(NUMBER_PATTERN,(String)value);
    }

    /**
     * 判断是否在为数字字符串，手机号和卡号校验,且非空
     * @param value 数值
     * @param args 参数
     * @return 返回是否大于最大值
     */
    public static boolean isMobileAndM(Object value, List<Object> args){
        log.debug("isMobile({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return false;
        }
        return Validator.isMobile((String)value);
    }

    /**
     * 判断是否在为卡号，且判断最大长度
     * @param value 数值
     * @param args 参数
     * @return 返回是否大于最大值
     */
    public static boolean isCardNoAndMaxLen(Object value, List<Object> args){
        log.debug("isCardNoAndMaxLen({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return true;
        }
        if(!Pattern.matches(NUMBER_PATTERN,(String)value)){//格式错误非数字
            return false;
        }
        return ObjectUtil.length(value) <= (Integer) args.get(0);
    }
    /**
     * 判断是否在为卡号，且判断最大长度,且非空
     * @param value 数值
     * @param args 参数
     * @return 返回是否大于最大值
     */
    public static boolean isCardNoAndMaxLenAndM(Object value, List<Object> args){
        log.debug("isCardNoAndMaxLenAndM({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return false;
        }
        if(!Pattern.matches(NUMBER_PATTERN,(String)value)){//格式错误非数字
            return false;
        }
        return ObjectUtil.length(value) <= (Integer) args.get(0);
    }
    /**
     * 判断是否在为卡号，且判断最大长度
     * @param value 数值
     * @param args 参数
     * @return 返回是否大于最大值
     */
    public static boolean isCardNoAndSectionLen(Object value, List<Object> args){
        log.debug("isCardNoAndSectionLen({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return true;
        }
        if(!Pattern.matches(NUMBER_PATTERN,(String)value)){//格式错误非数字
            return false;
        }
        try {
            if(ObjectUtil.length(value) < (int) args.get(0)){
                return false;
            }
            return ObjectUtil.length(value) <= (int) args.get(1);
        }catch (Exception e){
            log.error("校验参数异常isCardNoAndSectionLen:",e);
            return false;
        }
    }
    /**
     * 判断是否在为卡号，且判断最大长度,且非空
     * @param value 数值
     * @param args 参数
     * @return 返回是否大于最大值
     */
    public static boolean isCardNoAndSectionLenAndM(Object value, List<Object> args){
        log.debug("isCardNoAndSectionLenAndM({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return false;
        }
        if(!Pattern.matches(NUMBER_PATTERN,(String)value)){//格式错误非数字
            return false;
        }
        try {
            if(ObjectUtil.length(value) < (int) args.get(0)){
                return false;
            }
            return ObjectUtil.length(value) <= (int) args.get(1);
        }catch (Exception e){
            log.error("校验参数异常isCardNoAndSectionLenAndM:",e);
            return false;
        }
    }
    /**
     * 是否正整数，大于最小值且小于等于最大值，可为空
     * @param value 数值
     * @param args 参数
     * @return 返回
     */
    public static boolean isPIntergerInSectionVaule(Object value, List<Object> args) {
        log.debug("isPIntergerWithMaxLen({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return true;
        }
        if (!NumberUtil.isInteger((String) value)) {
            return false;
        }
        try {
            int v = Integer.parseInt((String)value);
            int minValue = (int) args.get(0);
            int maxValue = (int) args.get(1);
            if(v < minValue){
                return false;
            }
            return v <= maxValue;
        }catch (Exception e){
            log.error("校验参数异常isPIntergerWithMaxLen:",e);
            return false;
        }
    }
    /**
     * 是否正整数，大大于最小值且小于等于最大值，不可为空
     * @param value 数值
     * @param args 参数
     * @return 返回
     */
    public static boolean isPIntergerInSectionVauleAndM(Object value, List<Object> args) {
        log.debug("isPIntergerWithMaxLen({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return false;
        }
        if (!NumberUtil.isInteger((String) value)) {
            return false;
        }
        try {
            int v = Integer.parseInt((String)value);
            int minValue = (int) args.get(0);
            int maxValue = (int) args.get(1);
            if(v < minValue){
                return false;
            }
            return v <= maxValue;
        }catch (Exception e){
            log.error("校验参数异常isPIntergerWithMaxLen:",e);
            return false;
        }
    }

    /**
     * 判断字段值是否包含在给定值中，可为空
     * @param value 数值
     * @param args 参数
     * @return 返回
     */
    public static boolean isInValues(Object value, List<Object> args){
        log.debug("isInValues({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return true;
        }
        try {
            String values = (String) args.get(0);
            String[] allValues = values.split(",");
            if(CharSequenceUtil.equalsAny((String) value, allValues)){
                return true;
            }
        }catch (Exception e){
            log.error("数据校验异常isInValues:", e);
            return false;
        }
        return false;
    }

    /**
     * 判断字段值是否包含在给定值中，不可为空
     * @param value 数值
     * @param args 参数
     * @return 返回
     */
    public static boolean isInValuesAndM(Object value, List<Object> args){
        log.debug("isInValues({}{})", value, args);
        if(StrUtil.isBlankIfStr(value)){
            return false;
        }
        try {
            String values = (String) args.get(0);
            String[] allValues = values.split(",");
            if(CharSequenceUtil.equalsAny((String) value, allValues)){
                return true;
            }
        }catch (Exception e){
            log.error("数据校验异常isInValues:", e);
            return false;
        }
        return false;
    }

}
